﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Timers;
using System.Windows;
using Sinacor.Infra.UI.Common;
using Sinacor.Infra.UI.Controls.SmartClient;
using Sinacor.Infra.UI.Desktop.SmartClient;
using Sinacor.Infra.UI.Messaging;
using Sinacor.Infra.UI.Messaging.Internal;
using Sinacor.Infra.UI.Messaging.SmartClient;
using Sinacor.Infra.UI.Security.Licensing;
using Sinacor.Infra.UI.Session;
using Sinacor.Infra.UI.Settings;
using Sinacor.UI.Application.Menu.Model;
using Sinacor.UI.Application.Menu.Presenter;
using Sinacor.UI.Application.Menu.View.SmartClient;
using Sinacor.UI.Application.Settings.SmartClient;
using System.Windows.Controls;
using System.Windows.Input;
using System.Windows.Media.Animation;
using System.Drawing;
using System.Windows.Data;
using Sinacor.Infra.UI.HelpViewer.Client;
using Sinacor.Infra.UI.Favorites;
using System.Linq;
using System.IO;
using System.Threading;
using System.Runtime.Remoting.Messaging;
using Microsoft.Win32;
using PSE.Framework.Configuration;
using PSE.Framework.ErrorLogging;
using PSE.Framework.UI.Resources;
using PSE.Framework.UI.Settings;
using Sinacor.Infra.Common.Security.Authentication.Credentials;


namespace Sinacor.UI.Application.Menu.SmartClient
{
    public enum DockPosition
    {
        ToLeft,
        ToRight,
        ToDefaultPosition
    }

    public partial class Menu : SinacorWindowMenu, Presenter.IMenu
    {
        #region Attributes

        private SinacorMenu _menu;
        private MenuPresenter _presenter;
        private DesktopVirtual _virtualDesktop;
        private WindowController _windowController;
        private SessionManager _sessionaManager;
        private WPFMessageManager _messageManager;
        private ApplicationSettings _appSettings;
        private LicensingManager _licensingManager;
        private FavoritesManager _favoritesManager;
        private SinacorZoom _zoomControl;
        private SinacorMenuState _dockPosition = SinacorMenuState.DockedLeft;
        private System.Timers.Timer _menuTimer;
        private SinacorContextMenu _contextMenuModule;
        private SinacorContextMenu _contextMenuPublicFavorite;
        private SinacorContextMenu _contextMenuPrivateFavorite;
        private List<Company> _companies;
        private int _numberOfChildrenOpened;
        private bool _isAnimating = false;
        private bool _hasLoadedCompany = false;
        private bool _hasChildrenOpened = false;
        private double _dockLeftXPosition;
        private double _dockRightXPosition;
        private double _dockLeftYPosition;
        private double _dockRightYPosition;
        private double _windowCenterXPosition;
        private double _windowCenterYPosition;
        private double _lastMenuXPosition;
        private double _lastMenuYPosition;
        private double _dockInterval = 5;
        private const double _windowFloatingWidth = 139;
        private const double _windowFloatingHeight = 317;
        private const double _windowDockedWidth = 30;
        private const double _windowDockedHeight = 290;
        private const double _windowResizeAnimationDuration = 300;
        private const double _windowMoveAnimationDuration = 600;

        /// <summary>
        /// Handler do contador do menu
        /// </summary>
        delegate void TimerDockMenuDelegate();

        #endregion

        #region Controle de mudanca do tamanho do work area
        //TODO: Solucao temporaria para o reposicionamento do menu quando a workarea for alterada
        //devera ser substituido pela recuperacao da mensagem do windows que assinale que a workarea foi alterada        
        private ManualResetEvent _workAreadCheckStop;
        private Thread _workAreadCheck;
        private System.Windows.Rect _actualArea;
        public void RefreshMenuPosition()
        {
            bool hasChanges;
            System.Windows.Rect area;
            //loop onde e verificado se a workarea foi alterada para reposicionar o menu
            while (!_workAreadCheckStop.WaitOne(500))
            {
                hasChanges = true;
                area = SystemParameters.WorkArea;

                if (_actualArea != null)
                {
                    hasChanges = false;
                    hasChanges = _actualArea.Height != area.Height || _actualArea.Width != area.Width || _actualArea.Top != area.Top || _actualArea.Left != area.Left;
                }

                if (hasChanges)
                {
                    this.Dispatcher.Invoke(new Action(delegate()
                    {
                        Menu_StateChanged(new SinacorMenuStateChangedEventArgs(this._menu.State));
                    }));
                }
                _actualArea = area;
            }
        }

        #endregion

        #region Constructor

        /// <summary>
        /// Instancia e prepara um Menu
        /// </summary>
        public Menu()
        {
            this.ShowInTaskbar = false;

            System.Windows.Rect area = SystemParameters.WorkArea;// System.Windows.Forms.Screen.PrimaryScreen.WorkingArea;

            this._windowCenterXPosition = (area.Left + (area.Width / 2)) - (this.Width / 2);
            this._windowCenterYPosition = (area.Top + (area.Height / 2)) - (this.Height / 2);

            this._dockLeftXPosition = area.Left;
            this._dockLeftYPosition = _windowCenterYPosition;

            this._dockRightXPosition = area.Right;
            this._dockRightYPosition = _windowCenterYPosition;

            this._lastMenuXPosition = _windowCenterXPosition;
            this._lastMenuYPosition = _windowCenterYPosition;

            this.CenterWindow(_windowCenterXPosition, _windowCenterYPosition);

            this._menu = new SinacorMenu(LoadCompaniesMenu(), SinacorMenuType.Root);
            this._menu.StateChanged += new SinacorMenu.SinacorMenuStateChangedHandler(Menu_StateChanged);
            this.Content = _menu;

            this._messageManager = new WPFMessageManager();
            this._virtualDesktop = DesktopVirtual.GetInstance();
            this._windowController = new WindowController();
            this._sessionaManager = SessionManager.GetInstance();
            this._appSettings = ApplicationSettings.GetInstance();
            this._licensingManager = LicensingManager.GetInstance();
            this._favoritesManager = FavoritesManager.GetInstance();

            this._messageManager.OnInternalMessageArrival += new WPFMessageManager.WPFInternalMessageDelegate(MessageManager_OnInternalMessageArrival);
            this.PreviewMouseMove += new MouseEventHandler(Menu_PreviewMouseMove);
            this.MouseLeave += new MouseEventHandler(Menu_MouseLeave);
            this.PreviewKeyDown += new KeyEventHandler(Menu_PreviewKeyDown);
            this.Loaded += new RoutedEventHandler(Menu_Loaded);

            this.LoadMenuLocalSettings();
            this.LoadSkins();
            this.LoadLanguages();
            this.LoadMenuDockPositions();
            this.LoadZoomOptions();

            _contextMenuModule = new SinacorContextMenu();
            _contextMenuModule.Opened += new RoutedEventHandler(ContextMenuModule_Opened);
            _contextMenuModule.Items.Add(new ContextMenuItemModule("Common.Menu.Message.AdicionarFavoritoTodasEmpresas", new RoutedEventHandler(ContextMenuModuleAllCompany_Click)));
            _contextMenuModule.Items.Add(new ContextMenuItemModule("Common.Menu.Message.AdicionarFavoritoSomenteEmpresa", new RoutedEventHandler(ContextMenuModuleCompany_Click)));
            _contextMenuModule.Items.Add(new ContextMenuItemModule("Common.Menu.Message.ExcluirFavoritoTodasEmpresas", new RoutedEventHandler(ContextMenuModuleExcludeAllCompany_Click)));
            _contextMenuModule.Items.Add(new ContextMenuItemModule("Common.Menu.Message.ExcluirFavoritoEmpresaSomenteEmpresa", new RoutedEventHandler(ContextMenuModuleExcludeCompany_Click)));
            _contextMenuModule.SetResourceReference(System.Windows.Controls.ContextMenu.StyleProperty, "FavoritesContextMenu");

            _contextMenuPublicFavorite = new SinacorContextMenu();
            _contextMenuPublicFavorite.Opened += new RoutedEventHandler(ContextMenuPublicFavorite_Opened);
            _contextMenuPublicFavorite.Items.Add(new ContextMenuItemFavorite("Common.Menu.Message.ExcluirFavoritoTodasEmpresas", new RoutedEventHandler(ContextMenuPublicFavorite_Click)));
            _contextMenuPublicFavorite.SetResourceReference(System.Windows.Controls.ContextMenu.StyleProperty, "FavoritesContextMenu");

            _contextMenuPrivateFavorite = new SinacorContextMenu();
            _contextMenuPrivateFavorite.Opened += new RoutedEventHandler(ContextMenuPrivateFavorite_Opened);
            _contextMenuPrivateFavorite.Items.Add(new ContextMenuItemFavorite("Common.Menu.Message.ExcluirFavoritoEmpresaSomenteEmpresa", new RoutedEventHandler(ContextMenuPrivateFavorite_Click)));
            _contextMenuPrivateFavorite.SetResourceReference(System.Windows.Controls.ContextMenu.StyleProperty, "FavoritesContextMenu");

            this._presenter = new MenuPresenter(this);

            if (_dockInterval > 0)
            {
                this._menuTimer = new System.Timers.Timer();
                this._menuTimer.Elapsed += new ElapsedEventHandler(CheckTimer);
                this._menuTimer.Interval = _dockInterval * 1000;
                this._menuTimer.AutoReset = true;
            }

            //solucao temporaria para o reposicionamento do menu qndo a workarea for alterada
            this.Closed += new EventHandler(Menu_Closed);
            _workAreadCheckStop = new ManualResetEvent(false);
            _workAreadCheck = new Thread(new ThreadStart(RefreshMenuPosition));
            _workAreadCheck.Start();
        }

        void Menu_Closed(object sender, EventArgs e)
        {
            //parar o loop de verificacao 
            _workAreadCheckStop.Set();
        }

        #endregion

        #region Create Menu Items

        /// <summary>
        /// Cria itens do menu
        /// </summary>
        /// <param name="header">Cabeçalho</param>
        /// <param name="icon">Icone</param>
        /// <param name="SeparatorVisibility">Visibilidade do Separador</param>
        /// <param name="hasItems">Possui ou não filhos</param>
        /// <returns>Retorna um item de menu</returns>
        RootMenuItem CreateRootMenuItem(string header, string icon, bool hasItems, MenuItemType itemType, SinacorMenuType menuType, RootMenuContentType subMenuContainerType, bool isEnabled, bool staysOpenOnClick)
        {
            RootMenuItem item = new RootMenuItem();

            if (!String.IsNullOrEmpty(icon))
            {
                item.SetResourceReference(RootMenuItem.IconProperty, icon);
                item.IconName = icon;
            }

            item.SetResourceReference(RootMenuItem.HeaderProperty, header);
            item.ItemType = itemType;
            item.MenuType = menuType;
            item.SubMenuContainerType = subMenuContainerType;
            item.IsEnabled = isEnabled;
            item.Click += new RoutedEventHandler(MenuItem_Click);
            item.SubmenuOpened += new RoutedEventHandler(MenuItem_SubmenuOpened);
            item.SubmenuClosed += new RoutedEventHandler(MenuItem_SubmenuClosed);
            item.StaysOpenOnClick = staysOpenOnClick;

            return item;
        }

        /// <summary>
        /// Converte um item vindo da model para um item de menu que será adicionado no menu
        /// </summary>
        /// <param name="subItemPresenter">Item do menu como classe presenter</param>
        /// <param name="module">Modulo corrente</param>
        /// <returns>Item do menu convertido</returns>
        SubMenuItem AddItemToMenu(Model.MenuItem subItemPresenter, Module module)
        {
            SubMenuItem subItem = new SubMenuItem();
            subItem.SubItemAssembly = subItemPresenter.Assembly;
            subItem.SubItemClass = subItemPresenter.Classe;
            subItem.SubItemId = subItemPresenter.Id;
            subItem.SetResourceReference(SubMenuItem.HeaderProperty, subItemPresenter.Name);
            subItem.SubItemName = subItemPresenter.Name;
            subItem.SubItemModuleName = string.Format("Common.Menu.Label.{0}", module.Id);
            subItem.SubItemModuleID = module.Id;
            subItem.SubItemRole = subItemPresenter.Role;

            return subItem;
        }

        #endregion

        #region MenuItem Events

        /// <summary>
        /// Assina o evento quando uma aba é aberta
        /// </summary>
        void MenuItem_SubmenuOpened(object sender, RoutedEventArgs e)
        {
            _hasChildrenOpened = true;
            _numberOfChildrenOpened++;
            if (e.OriginalSource is RootMenuItem && ((RootMenuItem)e.OriginalSource).ItemType == MenuItemType.ZoomButton)
            {
                _zoomControl = ((ZoomMenuItem)((RootMenuItem)this._menu.Items[5]).Items[0]).ZoomControl as SinacorZoom;
                if (_zoomControl != null && _zoomControl is SinacorZoom)
                {
                    _zoomControl.ZoomChanged += new SinacorZoom.ZoomChangedHandler(Menu_ZoomChanged);
                    _zoomControl.CurrentZoom = SinacorCurrentSettings.GetInstance().CurrentZoom;
                }
            }
        }

        /// <summary>
        /// Assina o evento quando uma aba é fechada
        /// </summary>
        void MenuItem_SubmenuClosed(object sender, RoutedEventArgs e)
        {
            _hasChildrenOpened = false;
            _numberOfChildrenOpened--;
            if (e.OriginalSource is RootMenuItem && ((RootMenuItem)e.OriginalSource).ItemType == MenuItemType.ZoomButton)
            {
                if (_zoomControl != null)
                {
                    _zoomControl.ZoomChanged -= new SinacorZoom.ZoomChangedHandler(Menu_ZoomChanged);
                    _zoomControl = null;
                }
            }
        }

        /// <summary>
        /// Assina o evento que é disparado quando um item do menu é selecionado
        /// </summary>
        void MenuItem_Click(object sender, RoutedEventArgs e)
        {
            if (e.OriginalSource is RootMenuItem)
            {
                RootMenuItem cls = (RootMenuItem)sender;
                if (cls.ItemType == MenuItemType.ExitButton)
                    this.CloseApplication();
                else if (cls.ItemType == MenuItemType.HelpButton)
                    this.ShowHelp();
                else if (cls.ItemType == MenuItemType.ChangeUserButton)
                    this.ChangeUser();
            }
            else if (e.OriginalSource is CompanyMenuItem)
            {
                CompanyMenuItem cls = (CompanyMenuItem)e.OriginalSource;
                if (!_hasLoadedCompany || !CheckWindowHasPendingActions())
                {
                    SetCompanyData(cls.CompanyName, cls.CompanyCGC, cls.CompanyID);

                    if (!this._licensingManager.ValidateCompany(cls.CompanyName, cls.CompanyCGC, cls.CompanyID))
                        SinacorMessageBox.Show((string)ResourceProviderManager.GetResourceProvider().TryGetResource("Common.Application.Message.NoLicense"), SinacorMessageBoxButton.Ok, SinacorMessageBoxImage.Exclamation);

                    this.EnableModuleMenuItem();

                    this.RefreshOpenedWindowsList();

                    _hasLoadedCompany = true;

                    this._menu.Items.MoveCurrentToPosition(1);
                    this.MoveSelectionToIndex(1);
                }
                else
                {
                    SinacorMessageBox.Show((string)ResourceProviderManager.GetResourceProvider().TryGetResource("Common.Message.OpenedMessageBoxWindowModal"), SinacorMessageBoxButton.Ok, SinacorMessageBoxImage.Exclamation);
                }
            }
            else if (e.OriginalSource is SubMenuItem)
            {
                SubMenuItem cls = (SubMenuItem)e.OriginalSource;
                OpenWindow(cls);
                OverwriteModuleItems(cls.SubItemModuleID);
            }
            else if (e.OriginalSource is FavoriteSubMenuItem)
            {
                FavoriteSubMenuItem cls = (FavoriteSubMenuItem)e.OriginalSource;

                bool isActive = false;

                foreach (SinacorWindow w in _virtualDesktop.GetDesktopVirtual(_sessionaManager.GetCurrentSession().TokenID))
                {
                    if (w.GetType().FullName == cls.Assembly.Replace(".dll", ".") + cls.ClassName)
                    {
                        InternalMessage message = new InternalMessage();
                        message.MessageId = MessageIds.WindowManager.SNC_WINDOW_RESTORE;
                        message.Message = w.GetHashCode();
                        _messageManager.SendMessage(message);
                        isActive = true;
                        break;
                    }
                }

                if (isActive)
                    this.SetMenuPositionAfterAction(this._dockPosition);
                else
                {
                    if (_menu.SelectedCompanyId != cls.ParentMenu.CompanyID)
                    {
                        if (!SetCompanyData(cls.ParentMenu.CompanyName, cls.ParentMenu.CompanyCGC, cls.ParentMenu.CompanyID))
                        {
                            return;
                        }
                    }

                    this.EnableModuleMenuItem();

                    this.RefreshOpenedWindowsList();

                    _hasLoadedCompany = true;

                    OpenWindow(cls);
                }
            }
            else if (e.OriginalSource is WindowMenuItem)
            {
                WindowMenuItem cls = (WindowMenuItem)e.OriginalSource;
                foreach (SinacorWindow w in _virtualDesktop.GetDesktopVirtual(_sessionaManager.GetCurrentSession().TokenID))
                {
                    if (w.GetHashCode() == cls.WindowID)
                    {
                        InternalMessage message = new InternalMessage();
                        message.MessageId = MessageIds.WindowManager.SNC_WINDOW_RESTORE;
                        message.Message = cls.WindowID;
                        _messageManager.SendMessage(message);
                        break;
                    }
                }
                this.SetMenuPositionAfterAction(this._dockPosition);
            }
            else if (e.OriginalSource is LanguageMenuItem)
            {
                this.ChangeHelpLanguage(((LanguageMenuItem)e.OriginalSource).LanguageID);
                this.SetMenuPositionAfterAction(this._dockPosition);
                RetrievedModules(_menu.SelectedCompanyId);
            }
            else if (e.OriginalSource is ThemeMenuItem)
            {
                this.ChangeTheme(((ThemeMenuItem)e.OriginalSource).ThemeID);
                this.SetMenuPositionAfterAction(this._dockPosition);
            }
            else if (e.OriginalSource is DockMenuItem)
            {
                this.ChangeDockedMenuPosition(((DockMenuItem)e.OriginalSource).DockedState);
                this.SetMenuPositionAfterAction(this._dockPosition);
                this.SaveMenuSettings();
            }
        }

        /// <summary>
        /// Trata o evento quando o botao "Home" é clicado para retornar todos os módulos
        /// </summary>
        void RollbackModules_Click(object sender, EventArgs e)
        {
            ((RootMenuItem)_menu.Items[1]).SubMenuContainerType = RootMenuContentType.Default;
            ((RootMenuItem)_menu.Items[1]).CommandBindings.Remove(new CommandBinding(SinacorMenuCommands.RollbackModules, RollbackModules_Click));

            LoadModules();
        }

        #endregion

        #region MessageManager

        /// <summary>
        /// Assina o evento de recebimento de mensagens
        /// </summary>
        /// <param name="internalMessage">Mensagem recebida</param>
        void MessageManager_OnInternalMessageArrival(InternalMessage internalMessage)
        {
            if (internalMessage.MessageId == MessageIds.WindowManager.SNC_WINDOW_OPEN || internalMessage.MessageId == MessageIds.WindowManager.SNC_WINDOW_CLOSE)
            {
                RefreshOpenedWindowsList();
            }
            else if (internalMessage.MessageId == MessageIds.Menu.SNC_MENU_RESTORE)
            {
                if (this._menu != null)
                    this._menu.State = SinacorMenuState.Floating;

                this.Activate();
            }
            else if (internalMessage.MessageId == MessageIds.Menu.SNC_MENU_ADD_FAVORITE_ALL_COMPANY)
            {
                AddMenuItemFavoriteAllCompany((Favorite)internalMessage.Message);
            }
            else if (internalMessage.MessageId == MessageIds.Menu.SNC_MENU_ADD_FAVORITE_COMPANY)
            {
                AddMenuItemFavoriteCompany((CompanyFavorite)internalMessage.Message);
            }
            else if (internalMessage.MessageId == MessageIds.Menu.SNC_MENU_EXCLUDE_FAVORITE_ALL_COMPANY)
            {
                RemoveMenuItemFavoriteAllCompany((Favorite)internalMessage.Message);
            }
            else if (internalMessage.MessageId == MessageIds.Menu.SNC_MENU_EXCLUDE_FAVORITE_COMPANY)
            {
                RemoveMenuItemFavoriteCompany((CompanyFavorite)internalMessage.Message);
            }
            else if (internalMessage.MessageId == MessageIds.Menu.SNC_MENU_REFRESH)
            {
                _virtualDesktop.ChangeDesktopVirtual(_sessionaManager.GetCurrentSession().TokenID);

                SetCompanyData();

                _companies = _presenter.RetrieveCompanies();

                ClearModuleMenuItem();

                this.LoadCompanies();
            }
        }

        #endregion

        #region Load Root Menus

        /// <summary>
        /// Carrega os temas instalados no sistema
        /// </summary>
        void LoadSkins()
        {
            SinacorMenuItem configs = ((SinacorMenuItem)this._menu.Items[4]);

            ConfigurationMenuItem skinTitle = new ConfigurationMenuItem();
            skinTitle.SetResourceReference(ConfigurationMenuItem.HeaderProperty, "Common.Menu.Label.Skins");
            configs.Items.Add(skinTitle);

            foreach (ClassToInstanceInformation theme in _appSettings.InstalledThemes)
            {
                ThemeMenuItem themeMenuItem = new ThemeMenuItem();
                themeMenuItem.ThemeID = theme.Name;
                themeMenuItem.SetResourceReference(ThemeMenuItem.HeaderProperty, string.Format("Common.Menu.Label.{0}", theme.Name));
                ((SinacorMenuItem)configs.Items[0]).Items.Add(themeMenuItem);
            }
        }

        /// <summary>
        /// Carrega as linguas instaladas no sistema
        /// </summary>
        void LoadLanguages()
        {
            SinacorMenuItem configs = ((SinacorMenuItem)this._menu.Items[4]);

            ConfigurationMenuItem languageTitle = new ConfigurationMenuItem();
            languageTitle.SetResourceReference(ConfigurationMenuItem.HeaderProperty, "Common.Menu.Label.Languages");
            configs.Items.Add(languageTitle);

            foreach (ClassToInstanceInformation lang in _appSettings.InstalledLanguages)
            {
                LanguageMenuItem languageMenuItem = new LanguageMenuItem();
                languageMenuItem.LanguageID = lang.Name;
                languageMenuItem.SetResourceReference(LanguageMenuItem.HeaderProperty, string.Format("Common.Menu.Label.{0}", lang.Name));
                ((SinacorMenuItem)configs.Items[1]).Items.Add(languageMenuItem);
            }
        }

        /// <summary>
        /// Carrega os possiveis posições do menu dockado
        /// </summary>
        void LoadMenuDockPositions()
        {
            SinacorMenuItem configs = ((SinacorMenuItem)this._menu.Items[4]);

            ConfigurationMenuItem menuDockStateTitle = new ConfigurationMenuItem();
            menuDockStateTitle.SetResourceReference(ConfigurationMenuItem.HeaderProperty, "Common.Menu.Label.DockedMenuState");
            configs.Items.Add(menuDockStateTitle);

            DockMenuItem dockLeft = new DockMenuItem();
            DockMenuItem dockRight = new DockMenuItem();

            dockLeft.DockedState = SinacorMenuState.DockedLeft;
            dockRight.DockedState = SinacorMenuState.DockedRight;

            dockLeft.SetResourceReference(DockMenuItem.HeaderProperty, "Common.Menu.Label.DockLeft");
            dockRight.SetResourceReference(DockMenuItem.HeaderProperty, "Common.Menu.Label.DockRight");

            ((SinacorMenuItem)configs.Items[2]).Items.Add(dockLeft);
            ((SinacorMenuItem)configs.Items[2]).Items.Add(dockRight);
        }

        /// <summary>
        /// Carrega as opções de zoom
        /// </summary>
        void LoadZoomOptions()
        {
            SinacorMenuItem zoom = ((SinacorMenuItem)this._menu.Items[5]);
            ZoomMenuItem zoomMenuItem = new ZoomMenuItem();
            zoomMenuItem.TemplateApplied += new SinacorMenuItem.TemplateAppliedHandler(zoomMenuItem_TemplateApplied);
            zoom.Items.Add(zoomMenuItem);
        }

        /// <summary>
        /// Implementa o evento quando o template do controle de zoom é aplicado
        /// </summary>
        void zoomMenuItem_TemplateApplied(SinacorMenuTemplateAppliedEventArgs e)
        {
            _zoomControl = e.ZoomControl;
            if (_zoomControl != null && _zoomControl is SinacorZoom)
            {
                _zoomControl.ZoomChanged += new SinacorZoom.ZoomChangedHandler(Menu_ZoomChanged);
                _zoomControl.CurrentZoom = SinacorCurrentSettings.GetInstance().CurrentZoom;
            }
        }

        #endregion

        #region Settings

        /// <summary>
        /// Salva as configurações de menu
        /// </summary>
        void SaveMenuSettings()
        {
            IConfigurationSettings<SinacorConfigurationObjectType> configurationSettings = ConfigurationSettingsManager<SinacorConfigurationObjectType>.GetConfigurationSettings();
            MenuConfigurationObject menuConfig = new MenuConfigurationObject();

            menuConfig.DockedPosition = _dockPosition;
            configurationSettings.Save((IConfigurationObject<SinacorConfigurationObjectType>)menuConfig);
        }

        /// <summary>
        /// Carrega as configurações de menu salvas
        /// </summary>
        void LoadMenuLocalSettings()
        {
            IConfigurationSettings<SinacorConfigurationObjectType> configurationSettings = ConfigurationSettingsManager<SinacorConfigurationObjectType>.GetLocalConfigurationSettings();
            IConfigurationObject<SinacorConfigurationObjectType> menuConfig = new MenuConfigurationObject();

            if (!configurationSettings.Load(ref menuConfig))
                ((MenuConfigurationObject)menuConfig).DockedPosition = SinacorMenuState.DockedLeft;

            _dockPosition = ((MenuConfigurationObject)menuConfig).DockedPosition;
            ChangeDockedMenuPosition(_dockPosition);
        }

        /// <summary>
        /// Carrega as configurações de menu salvas
        /// </summary>
        void LoadMenuServerSettings()
        {
            IConfigurationSettings<SinacorConfigurationObjectType> configurationSettings = ConfigurationSettingsManager<SinacorConfigurationObjectType>.GetServerConfigurationSettings();

            if (configurationSettings != null)
            {
                IConfigurationObject<SinacorConfigurationObjectType> menuConfig = new MenuConfigurationObject();

                if (configurationSettings.Load(ref menuConfig))
                {
                    _dockPosition = ((MenuConfigurationObject)menuConfig).DockedPosition;
                    ConfigurationSettingsManager<SinacorConfigurationObjectType>.GetLocalConfigurationSettings().Save(menuConfig);
                }
            }
        }

        #endregion

        #region Window Orientation

        /// <summary>
        /// Movimenta o menu
        /// </summary>
        void MoveWindow(double toX, double toY)
        {
            this.IsAnimating = true;
            this.BeginAnimation(SinacorWindowMenu.LeftProperty, MakeAnimation(toX, _windowMoveAnimationDuration, null));
            this.BeginAnimation(SinacorWindowMenu.TopProperty, MakeAnimation(toY, _windowMoveAnimationDuration, AnimationCompleted));
        }

        /// <summary>
        /// Redimensiona o menu
        /// </summary>
        void ResizeWindow(double width, double height, DockPosition dockPosition)
        {
            this.IsAnimating = true;

            switch (dockPosition)
            {
                case DockPosition.ToLeft:
                    this.BeginAnimation(SinacorWindowMenu.WidthProperty, MakeAnimation(width, _windowResizeAnimationDuration, null));
                    this.BeginAnimation(SinacorWindowMenu.HeightProperty, MakeAnimation(height, _windowResizeAnimationDuration, ResizeToLeftCompleted));
                    break;
                case DockPosition.ToRight:
                    this.BeginAnimation(SinacorWindowMenu.WidthProperty, MakeAnimation(width, _windowResizeAnimationDuration, null));
                    this.BeginAnimation(SinacorWindowMenu.HeightProperty, MakeAnimation(height, _windowResizeAnimationDuration, ResizeToRightCompleted));
                    break;
                case DockPosition.ToDefaultPosition:
                    this.BeginAnimation(SinacorWindowMenu.WidthProperty, MakeAnimation(width, _windowResizeAnimationDuration, null));
                    this.BeginAnimation(SinacorWindowMenu.HeightProperty, MakeAnimation(height, _windowResizeAnimationDuration, ResizeToDefaultPositionCompleted));
                    break;
            }
        }

        /// <summary>
        /// Centraliza o menu
        /// </summary>
        void CenterWindow(double x, double y)
        {
            this.Left = x;
            this.Top = y;
        }

        /// <summary>
        /// Docka o menu na esquerda
        /// </summary>
        void DockToLeft()
        {
            this.ResizeWindow(_windowDockedWidth, _windowDockedHeight, DockPosition.ToLeft);
        }

        /// <summary>
        /// Docka o menu na direita
        /// </summary>
        void DockToRight()
        {
            this.ResizeWindow(_windowDockedWidth, _windowDockedHeight, DockPosition.ToRight);
        }

        /// <summary>
        /// Desdocka o menu
        /// </summary>
        void UnDock()
        {
            this.ResizeWindow(_windowFloatingWidth, _windowFloatingHeight, DockPosition.ToDefaultPosition);
        }

        /// <summary>
        /// Metodo disparado pelo evento Completed quando uma animação do menu chega ao final
        /// </summary>
        void AnimationCompleted(object sender, EventArgs e)
        {
            this.IsAnimating = false;
        }

        /// <summary>
        /// Metodo disparado pelo evento Completed quando uma animação de redimensionamento do menu chega ao final
        /// </summary>
        void ResizeToLeftCompleted(object sender, EventArgs e)
        {
            //ajustar as propriedades width e height para se adequar ao espaço disponivel no desktop
            System.Windows.Rect area = SystemParameters.WorkArea;// System.Windows.Forms.Screen.PrimaryScreen.WorkingArea;

            _dockLeftXPosition = area.Left;
            _dockLeftYPosition = (area.Top + (area.Height / 2)) - (this.Height / 2);

            this.MoveWindow(_dockLeftXPosition, _dockLeftYPosition);
        }

        /// <summary>
        /// Metodo disparado pelo evento Completed quando uma animação de redimensionamento do menu chega ao final
        /// </summary>
        void ResizeToRightCompleted(object sender, EventArgs e)
        {
            //ajustar as propriedades width e height para se adequar ao espaço disponivel no desktop
            System.Windows.Rect area = SystemParameters.WorkArea;
            _dockRightXPosition = (area.Left + area.Width) - this.Width;
            _dockRightYPosition = (area.Top + (area.Height / 2)) - (this.Height / 2);

            this.MoveWindow(_dockRightXPosition, _dockRightYPosition);
        }

        /// <summary>
        /// Metodo disparado pelo evento Completed quando uma animação de redimensionamento do menu chega ao final
        /// </summary>
        void ResizeToDefaultPositionCompleted(object sender, EventArgs e)
        {
            //ajustar as propriedades width e height para se adequar ao espaço disponivel no desktop
            System.Windows.Rect area = SystemParameters.WorkArea; //System.Windows.Forms.Screen.PrimaryScreen.WorkingArea;
            _lastMenuXPosition = (area.Left + (area.Width / 2)) - (this.Width / 2);
            _lastMenuYPosition = (area.Top + (area.Height / 2)) - (this.Height / 2);

            this.MoveWindow(_lastMenuXPosition, _lastMenuYPosition);
        }

        /// <summary>
        /// Metodo responsavel por mover o foco e abrir um sub-menu de um indice especifico
        /// </summary>
        /// <param name="index">Indice que recebera o foco e abrirá o sub-nível</param>
        void MoveSelectionToIndex(int index)
        {
            ((System.Windows.Controls.MenuItem)this._menu.Items[index]).Focus();
            ((System.Windows.Controls.MenuItem)this._menu.Items[index]).IsSubmenuOpen = true;
        }

        #endregion

        #region Timer

        /// <summary>
        /// Reinicia o contador que docka o menu apos alguns segundos
        /// </summary>
        void ReStartDockingTimer()
        {
            if (_dockInterval > 0 && _hasLoadedCompany)
            {
                if (!this._menuTimer.Enabled)
                    this._menuTimer.Enabled = true;

                this._menuTimer.Stop();
                this._menuTimer.Start();
            }
        }

        /// <summary>
        /// Para o contador que docka o menu
        /// </summary>
        void StopDockingTimer()
        {
            if (_dockInterval > 0)
            {
                this._menuTimer.Stop();
                this._menuTimer.Enabled = false;
            }
        }

        /// <summary>
        /// Metodo responsavel por tratar o evento quando o contador do menu chega ao final
        /// </summary>
        void CheckTimer(object source, ElapsedEventArgs e)
        {
            this.Dispatcher.Invoke(System.Windows.Threading.DispatcherPriority.Send, new TimerDockMenuDelegate(TimerDockMenu));
            this.StopDockingTimer();
        }

        /// <summary>
        /// Metodo responsavel por dockar o menu quando o contador chega ao final
        /// </summary>
        void TimerDockMenu()
        {
            this._menu.State = this._dockPosition;
        }

        #endregion

        #region Menu Events

        /// <summary>
        /// Função que trata o evento quando o zoom é alterado
        /// </summary>
        void Menu_ZoomChanged(ZoomChangedEventArgs e)
        {
            _appSettings.ChangeZoom(e.ZoomValue);
        }

        /// <summary>
        /// Verifica se a licença é do tipo Trial e informa quantos dias faltam para a expiração.
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        void Menu_Loaded(object sender, RoutedEventArgs e)
        {
            int days_remaining;

            //Verifica o tempo se a liceça é Trial
            if (_licensingManager.ValidateLicenseTrial(out days_remaining))
                SinacorMessageBox.Show((string)ResourceProviderManager.GetResourceProvider().TryGetResource("Common.Application.Message.LicenseTrial", days_remaining), SinacorMessageBoxButton.Ok, SinacorMessageBoxImage.Exclamation);

            _companies = _presenter.RetrieveCompanies();
            this.LoadCompanies();

            //Chamar de forma assincrona o metodo que retorna as empresas do bando de dados
            BackgroundWorker bw = new BackgroundWorker();
            bw.DoWork += new DoWorkEventHandler(bw_DoWork);
            bw.RunWorkerCompleted += new RunWorkerCompletedEventHandler(bw_RunWorkerCompleted);
            bw.RunWorkerAsync();
        }

        void bw_DoWork(object sender, DoWorkEventArgs e)
        {
            this.RetrieveRemainingCompanies();
        }

        void bw_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
        {
            this.LoadCompanies();
        }

        /// <summary>
        /// Trata o evento ao manipular o teclado
        /// </summary>
        void Menu_PreviewKeyDown(object sender, System.Windows.Input.KeyEventArgs e)
        {
            if (!this.IsFocused)
                this._menu.Focus();
        }

        /// <summary>
        /// Metodo disparado pelo evento MouseMove quando o mouse é movimentado no menu
        /// </summary>
        void Menu_PreviewMouseMove(object sender, MouseEventArgs e)
        {
            this.StopDockingTimer();
            if (this._menu.State == SinacorMenuState.Floating && (!_hasChildrenOpened && _numberOfChildrenOpened == 0))
            {
                if (e.LeftButton == MouseButtonState.Pressed)
                {
                    this.DragMove();

                    if (this.HasAnimatedProperties)
                    {
                        this.BeginAnimation(Menu.LeftProperty, null);
                        this.BeginAnimation(Menu.TopProperty, null);
                    }

                    _lastMenuXPosition = this.Left;
                    _lastMenuYPosition = this.Top;
                }
            }
        }

        /// <summary>
        /// Metodo disparado pelo evento MouseLeave quando o mouse sai do menu
        /// </summary>
        void Menu_MouseLeave(object sender, MouseEventArgs e)
        {
            if (this._menu.State == SinacorMenuState.Floating)
                this.ReStartDockingTimer();
        }

        /// <summary>
        /// Metodo disparado pelo evento StateChanged quando o estado do menu é alterado
        /// </summary>
        void Menu_StateChanged(SinacorMenuStateChangedEventArgs e)
        {
            switch (e.MenuState)
            {
                case SinacorMenuState.DockedLeft:
                    this.DockToLeft();
                    this.CreateUndockCommandBinding();
                    this.Topmost = true;
                    break;
                case SinacorMenuState.DockedRight:
                    this.DockToRight();
                    this.CreateUndockCommandBinding();
                    this.Topmost = true;
                    break;
                case SinacorMenuState.Floating:
                    this.UnDock();
                    this.RemoveUndockCommandBinding();
                    this.ReStartDockingTimer();
                    this.Topmost = false;
                    break;
            }

            _hasChildrenOpened = false;
            _numberOfChildrenOpened = 0;
        }

        #endregion

        #region Create / Remove CommandBinding

        /// <summary>
        /// Trata o evento quando o botao "Sinacor" é clicado para retornar ao estado Flutuante
        /// </summary>
        void UndockCommandBinding_Click(object sender, EventArgs e)
        {
            this._menu.State = SinacorMenuState.Floating;
        }

        /// <summary>
        /// Metodo responsavel por criar os command bindings do menu
        /// </summary>
        void CreateUndockCommandBinding()
        {
            if (!this._menu.CommandBindings.Contains(new CommandBinding(SinacorMenuCommands.UndockMenu, UndockCommandBinding_Click)))
                this._menu.CommandBindings.Add(new CommandBinding(SinacorMenuCommands.UndockMenu, UndockCommandBinding_Click));
        }

        /// <summary>
        /// Metodo responsavel por destruir os command bindings do menu
        /// </summary>
        void RemoveUndockCommandBinding()
        {
            if (this._menu.CommandBindings.Contains(new CommandBinding(SinacorMenuCommands.UndockMenu, UndockCommandBinding_Click)))
                this._menu.CommandBindings.Remove(new CommandBinding(SinacorMenuCommands.UndockMenu, UndockCommandBinding_Click));
        }

        #endregion

        #region Help

        /// <summary>
        /// Evento de click do botão para exibir o aplicativo de ajuda do Sinacor
        /// </summary>
        private void ShowHelp()
        {
            HelpViewerClient help = new HelpViewerClient();
            help.ShowHelp();
        }

        /// <summary>
        /// Evento de click do botão para exibir o aplicativo de ajuda do Sinacor
        /// </summary>
        private void ChangeHelpLanguage(string language)
        {
            HelpViewerClient help = new HelpViewerClient();

            _appSettings.ChangeLanguage(language);

            help.ChangeLanguage(language);
        }

        #endregion

        #region Theme

        /// <summary>
        /// Evento de click do botão para exibir o aplicativo de ajuda do Sinacor
        /// </summary>
        private void ChangeTheme(string theme)
        {
            HelpViewerClient help = new HelpViewerClient();

            _appSettings.ChangeTheme(theme);

            help.ChangeTheme(theme);
        }

        #endregion

        #region Animation

        /// <summary>
        /// Verifica se o menu está em movimento
        /// </summary>
        public bool IsAnimating
        {
            get { return _isAnimating; }
            set
            {
                _isAnimating = value;
                this.IsHitTestVisible = !value;
            }
        }

        /// <summary>
        /// Metodo estatico responsavel por gerar as animacoes do menu
        /// </summary>
        static DoubleAnimation MakeAnimation(double to, double duration, EventHandler endEvent)
        {
            DoubleAnimation anim = new DoubleAnimation(to, TimeSpan.FromMilliseconds(duration));
            anim.AccelerationRatio = 0.2;
            anim.DecelerationRatio = 0.7;

            if (endEvent != null)
                anim.Completed += endEvent;
            return anim;
        }

        #endregion

        #region Load Companies / Modules

        /// <summary>
        /// Carrega o menu padrão do sinacor
        /// </summary>
        BindingList<object> LoadCompaniesMenu()
        {
            BindingList<object> items = new BindingList<object>();
            items.Add(CreateRootMenuItem("Common.Menu.Label.Empresas", "IconMenuCompany", true, MenuItemType.NormalButton, SinacorMenuType.Child, RootMenuContentType.Default, false, false));
            items.Add(CreateRootMenuItem("Common.Menu.Label.Modulos", "IconMenuModule", true, MenuItemType.NormalButton, SinacorMenuType.Child, RootMenuContentType.Default, false, false));
            items.Add(CreateRootMenuItem("Common.Menu.Label.Favoritos", "IconMenuFavorite", true, MenuItemType.NormalButton, SinacorMenuType.Child, RootMenuContentType.Default, false, false));
            items.Add(new Separator());
            items.Add(CreateRootMenuItem("Common.Menu.Label.Configuracao", "IconMenuSetting", true, MenuItemType.NormalButton, SinacorMenuType.Child, RootMenuContentType.Default, true, false));
            items.Add(CreateRootMenuItem("Common.Menu.Label.Zoom", "IconMenuZoom", true, MenuItemType.ZoomButton, SinacorMenuType.ZoomControl, RootMenuContentType.ZoomSubMenu, true, false));
            items.Add(CreateRootMenuItem("Common.Menu.Label.Janelas", "IconMenuWindows", true, MenuItemType.NormalButton, SinacorMenuType.Child, RootMenuContentType.Default, false, false));
            items.Add(CreateRootMenuItem("Common.Menu.Label.Ajuda", "IconMenuHelp", false, MenuItemType.HelpButton, SinacorMenuType.Child, RootMenuContentType.Default, true, false));
            items.Add(CreateRootMenuItem("Common.Label.ChangeUser", "IconMenuChangeUser", false, MenuItemType.ChangeUserButton, SinacorMenuType.Child, RootMenuContentType.Default, true, false));
            items.Add(CreateRootMenuItem("Common.Menu.Label.Sair", "IconMenuExit", false, MenuItemType.ExitButton, SinacorMenuType.Child, RootMenuContentType.Default, true, false));
            return items;
        }

        /// <summary>
        /// Metodo que carrega as empresas
        /// </summary>
        public void LoadCompanies()
        {
            RootMenuItem companyMenuItem = ((RootMenuItem)this._menu.Items[0]);
            companyMenuItem.Items.Clear();

            companyMenuItem.IsEnabled = true;

            if (_companies != null)
            {
                foreach (Company company in _companies.OrderBy(m => m.Name))
                {
                    companyMenuItem.Items.Add(new CompanyMenuItem(company.Id, company.Name, company.CGC, company.Name));
                }
            }

            if (_companies.Count == 1)
            {
                this.EnableModuleMenuItem();

                this.SetCompanyData(_companies[0].Name, _companies[0].CGC, _companies[0].Id);

                if (!this._licensingManager.ValidateCompany(_companies[0].Name, _companies[0].CGC, _companies[0].Id))
                    SinacorMessageBox.Show((string)ResourceProviderManager.GetResourceProvider().TryGetResource("Common.Application.Message.NoLicense"), SinacorMessageBoxButton.Ok, SinacorMessageBoxImage.Exclamation);

                this.MoveSelectionToIndex(1);
                _hasLoadedCompany = true;
            }

            LoadFavorites();
        }

        /// <summary>
        /// Carrega os módulos a partir da empresa selecionada
        /// </summary>
        /// <param name="modules"></param>
        public void LoadModules()
        {
            RootMenuItem modulosMenu = ((RootMenuItem)this._menu.Items[1]);

            modulosMenu.Items.Clear();

            List<Module> modules = _companies.Find(c => c.Id == _menu.SelectedCompanyId).Modules;

            if (modules != null)
            {
                foreach (Module module in modules.OrderBy(m => m.Name))
                {
                    foreach (ModuleInformation modInfo in _appSettings.InstalledModules)
                    {
                        if (modInfo.Name == module.Id)
                        {
                            ModuleMenuItem menuItem = new ModuleMenuItem();
                            menuItem.ModuleID = module.Id;
                            menuItem.ModuleName = module.Name;
                            menuItem.SetResourceReference(ModuleMenuItem.HeaderProperty, string.Format("Common.Menu.Label.{0}", module.Id));
                            modulosMenu.Items.Add(menuItem);

                            if (module.Items != null && module.Items.Count > 0)
                            {
                                foreach (Model.MenuItem subItemPresenter in module.Items.OrderBy(m => m.Text))
                                {
                                    SinacorMenuItem itemTeste = modulosMenu.Items[modulosMenu.Items.Count - 1] as SinacorMenuItem;

                                    if (!(String.IsNullOrEmpty(subItemPresenter.Assembly) && (subItemPresenter.Children == null || subItemPresenter.Children.Count == 0)))
                                    {
                                        SubMenuItem item = AddItemToMenu(subItemPresenter, module);

                                        itemTeste.Items.Add(item);

                                        if (subItemPresenter.Children != null && subItemPresenter.Children.Count > 0)
                                            this.AddChildrenToMenu(subItemPresenter, module, item);
                                        else
                                            item.ContextMenu = _contextMenuModule;
                                    }
                                }
                            }
                            break;
                        }
                    }
                }
            }
        }

        /// <summary>
        /// Adiciona um nivel "filho" a mais no menu
        /// </summary>
        /// <param name="menuItem">Item do menu que receberá o filho</param>
        /// <param name="module">Informacao do modulo corrente</param>
        /// <param name="container">Container onde o sub-nível será criado</param>
        void AddChildrenToMenu(Model.MenuItem menuItem, Module module, SinacorMenuItem container)
        {
            if (menuItem.Children != null && menuItem.Children.Count > 0)
            {
                foreach (Model.MenuItem child in menuItem.Children.OrderBy(m => m.Text))
                {
                    if (!(String.IsNullOrEmpty(child.Assembly) && (child.Children == null || child.Children.Count == 0)))
                    {
                        SubMenuItem subItem = AddItemToMenu(child, module);

                        container.Items.Add(subItem);

                        if (child.Children != null && child.Children.Count > 0)
                            this.AddChildrenToMenu(child, module, subItem);
                        else
                            subItem.ContextMenu = _contextMenuModule;
                    }
                }
            }
        }

        void RetrievedModules(int companyId)
        {
            Company company = _companies.Find(c => c.Id == companyId);
            if (company != null && company.Modules == null)
                company.Modules = _presenter.RetrieveModules(companyId);

            this.LoadModules();
        }

        public void RetrieveRemainingCompanies()
        {
            foreach (Company company in _companies)
            {
                if (company.Modules == null)
                {
                    company.Modules = _presenter.RetrieveModules(company.Id, false);
                }
            }
        }

        /// <summary>
        /// Metodo que cria token da empresa e popula os itens de módulos do menu a partir da empresa informada
        /// </summary>
        bool SetCompanyData()
        {
            Company company = _companies.Find(c => c.Id == _menu.SelectedCompanyId);

            if (company != null)
            {
                return SetCompanyData(company.Name, company.CGC, company.Id);
            }
            else
            {
                return false;
            }
        }

        /// <summary>
        /// Metodo que cria token da empresa e popula os itens de módulos do menu a partir da empresa informada
        /// </summary>
        /// <param name="companyName">Nome da Empresa</param>
        /// <param name="companyID">ID da Empresa</param>
        /// <param name="companyName">CGC da Empresa</param>
        bool SetCompanyData(string companyName, string companyCGC, int companyID)
        {
            bool cont = true;

            if (_virtualDesktop.GetDesktopVirtual().Count > 0 && _virtualDesktop.GetDesktopVirtual()[_sessionaManager.GetCurrentSession().TokenID].Count > 0)
            {
                if (SinacorMessageBox.Show(FindResource("ControleAcesso.Menu.Message.AvisoTrocaEmpresa").ToString(), SinacorMessageBoxButton.YesNo) == SinacorMessageBoxResult.Yes)
                    cont = true;
                else
                    cont = false;
            }

            if (cont)
            {

                Sinacor.Infra.UI.Authentication.Company company = new Sinacor.Infra.UI.Authentication.Company();

                company.Id = companyID;
                company.Name = companyName;
                company.CGC = companyCGC;

                string tokenID = _sessionaManager.CreateSession(_sessionaManager.GetCurrentSession().User, company).TokenID;

                _virtualDesktop.ChangeDesktopVirtual(tokenID);

                //Altera a Credencial com a nova empresa selecionada.

                CredentialRepository cr = CredentialRepository.GetInstance();

                cr.UserInfo.CompanyId = companyID;


                this._menu.SelectedCompany = companyName;
                this._menu.SelectedCompanyId = companyID;

                this.RetrievedModules(companyID);

                ((RootMenuItem)_menu.Items[1]).SubMenuContainerType = RootMenuContentType.Default;
                ((RootMenuItem)_menu.Items[1]).CommandBindings.Remove(new CommandBinding(SinacorMenuCommands.RollbackModules, RollbackModules_Click));
            }

            return cont;
        }

        #endregion

        #region Close

        /// <summary>
        /// Metodo que fecha o aplicativo
        /// </summary>
        void CloseApplication()
        {
            WPFMessageManager messageManager = new WPFMessageManager();
            InternalMessage internalMessage = new InternalMessage();
            internalMessage.MessageId = MessageIds.Application.SNC_APPLICATION_CLOSE;
            internalMessage.Message = this;
            messageManager.SendMessage(internalMessage);
        }

        void ChangeUser()
        {
            if (SinacorMessageBox.Show((string)ResourceProviderManager.GetResourceProvider().TryGetResource("Infra.UI.Message.ConfirmacaoTrocaUsuario"), SinacorMessageBoxButton.YesNo, SinacorMessageBoxImage.Question) == SinacorMessageBoxResult.Yes)
            {
                WPFMessageManager messageManager = new WPFMessageManager();
                InternalMessage internalMessage = new InternalMessage();
                internalMessage.MessageId = MessageIds.Application.SNC_APPLICATION_CHANGE_USER;
                internalMessage.Message = this;
                messageManager.SendMessage(internalMessage);
            }
        }

        #endregion

        #region Open Window
        /// <summary>
        /// Método que abre a janela requisitada
        /// </summary>
        /// <param name="moduleName">Nome do módulo</param>
        /// <param name="itemName">Nome do janela</param>
        /// <param name="assembly">Nome do assembly</param>
        /// <param name="className">Nome da clase</param>
        void OpenWindow(SinacorMenuItem menu)
        {
            string moduleName = string.Empty;
            string itemName = string.Empty;
            string assembly = string.Empty;
            string className = string.Empty;
            string role = string.Empty;

            if (menu is SubMenuItem)
            {
                moduleName = ((SubMenuItem)menu).SubItemModuleName;
                itemName = ((SubMenuItem)menu).SubItemName;
                assembly = ((SubMenuItem)menu).SubItemAssembly;
                className = ((SubMenuItem)menu).SubItemClass;
                role = ((SubMenuItem)menu).SubItemRole;
            }
            else if (menu is FavoriteSubMenuItem)
            {
                moduleName = ((FavoriteSubMenuItem)menu).ModuleName;
                itemName = ((FavoriteSubMenuItem)menu).ItemName;
                assembly = ((FavoriteSubMenuItem)menu).Assembly;
                className = ((FavoriteSubMenuItem)menu).ClassName;
                role = ((FavoriteSubMenuItem)menu).MenuRole;
            }

            List<string> MenuPath = new List<string>();
            MenuPath.Add(moduleName);
            LoadParentMenuPath(menu, MenuPath);
            MenuPath.Add(itemName);

            Session session = Sinacor.Infra.UI.Session.SessionManager.GetInstance().GetCurrentSession();
            Company comp = _companies.FirstOrDefault(c => c.Id == session.Company.Id);

            _windowController.OpenWindow(assembly, className, MenuPath, role, comp);

            this._menu.SetResourceReference(SinacorMenu.SelectedModuleProperty, moduleName);
            this.SetMenuPositionAfterAction(this._dockPosition);
        }

        private void LoadParentMenuPath(SinacorMenuItem menu, List<string> MenuPath)
        {
            if (menu.Parent != null && (menu is SinacorMenuItem))
            {
                if (menu.Parent is SubMenuItem)
                {
                    LoadParentMenuPath((SinacorMenuItem)menu.Parent, MenuPath);
                    MenuPath.Add(((SubMenuItem)menu.Parent).SubItemName);
                }

                if (menu.Parent is FavoriteSubMenuItem)
                {
                    LoadParentMenuPath((SinacorMenuItem)menu.Parent, MenuPath);
                    MenuPath.Add(((FavoriteSubMenuItem)menu.Parent).ItemName);
                }
            }
        }

        #endregion

        #region ContextMenu

        /// <summary>
        /// Evento que trata a inclusão de um favorito para todas as empresas
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        void ContextMenuModuleAllCompany_Click(object sender, RoutedEventArgs e)
        {
            ContextMenuItemModule item = (ContextMenuItemModule)e.OriginalSource;

            Favorite favorite = new Favorite(item.ParentMenu.SubItemAssembly, item.ParentMenu.SubItemClass, item.ParentMenu.SubItemModuleName.Trim(), item.ParentMenu.SubItemModuleID.Trim(), item.ParentMenu.SubItemName.Trim(), item.ParentMenu.SubItemRole.Trim());

            if (_favoritesManager.AddFavorite(favorite))
            {
                AddMenuItemFavoriteAllCompany(favorite);
                ShowFavoritesIcons(favorite);
            }
            else
                SinacorMessageBox.Show((string)ResourceProviderManager.GetResourceProvider().TryGetResource("Common.Menu.Message.LimiteFavoritosExcedidoTodasEmpresas"), SinacorMessageBoxButton.Ok, SinacorMessageBoxImage.Information);
        }

        /// <summary>
        /// Evento que trata a inclusão de um favorito a empresa selecionada
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        void ContextMenuModuleCompany_Click(object sender, RoutedEventArgs e)
        {
            ContextMenuItemModule item = (ContextMenuItemModule)e.OriginalSource;

            CompanyFavorite companyFavorite = new CompanyFavorite(_menu.SelectedCompanyId, item.ParentMenu.SubItemAssembly, item.ParentMenu.SubItemClass, item.ParentMenu.SubItemModuleName, item.ParentMenu.SubItemModuleID, item.ParentMenu.SubItemName, item.ParentMenu.SubItemRole);

            if (_favoritesManager.AddFavorite(companyFavorite))
            {
                AddMenuItemFavoriteCompany(companyFavorite);
                ShowFavoritesIcons(companyFavorite);
            }
            else
                SinacorMessageBox.Show((string)ResourceProviderManager.GetResourceProvider().TryGetResource("Common.Menu.Message.LimiteFavoritosExcedidoSomenteEmpresa", _menu.SelectedCompany), SinacorMessageBoxButton.Ok, SinacorMessageBoxImage.Information);
        }

        /// <summary>
        /// Evento que trata a exclusão de um favorito para todas as empresas no root-menu de módulos
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        void ContextMenuModuleExcludeAllCompany_Click(object sender, RoutedEventArgs e)
        {
            ContextMenuItemModule cls = (ContextMenuItemModule)e.OriginalSource;

            Favorite favorite = new Favorite() { Assembly = cls.ParentMenu.SubItemAssembly, ClassName = cls.ParentMenu.SubItemClass };

            if (SinacorMessageBox.Show((string)ResourceProviderManager.GetResourceProvider().TryGetResource("Common.Menu.Message.ConfirmacaoExclusaoFavoritoTodasEmpresas"), SinacorMessageBoxButton.YesNo, SinacorMessageBoxImage.Question) == SinacorMessageBoxResult.Yes)
            {
                if (_favoritesManager.RemoveFavorite(favorite.Assembly, favorite.ClassName))
                {
                    RemoveMenuItemFavoriteAllCompany(favorite);

                    ShowFavoritesIcons(favorite);
                }
            }
        }

        /// <summary>
        /// Evento que trata a exclusão de um favorito para a empresa selecionada no root-menu de módulos
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        void ContextMenuModuleExcludeCompany_Click(object sender, RoutedEventArgs e)
        {
            ContextMenuItemModule cls = (ContextMenuItemModule)e.OriginalSource;

            CompanyFavorite companyFavorite = new CompanyFavorite() { Assembly = cls.ParentMenu.SubItemAssembly, ClassName = cls.ParentMenu.SubItemClass, CompanyId = _menu.SelectedCompanyId };

            string message = (string)ResourceProviderManager.GetResourceProvider().TryGetResource("Common.Menu.Message.ConfirmacaoExclusaoFavoritoSomenteEmpresa", _menu.SelectedCompany);

            if (SinacorMessageBox.Show(message, SinacorMessageBoxButton.YesNo, SinacorMessageBoxImage.Question) == SinacorMessageBoxResult.Yes)
            {
                if (_favoritesManager.RemoveFavorite(companyFavorite.CompanyId, companyFavorite.Assembly, companyFavorite.ClassName))
                {
                    RemoveMenuItemFavoriteCompany(companyFavorite);

                    ShowFavoritesIcons(companyFavorite);
                }
            }
        }

        /// <summary>
        /// Evento que trata a exclusão de um favorito para todas as empresas no root-menu de favoritos
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        void ContextMenuPublicFavorite_Click(object sender, RoutedEventArgs e)
        {
            ContextMenuItemFavorite cls = (ContextMenuItemFavorite)e.OriginalSource;

            if (SinacorMessageBox.Show((string)ResourceProviderManager.GetResourceProvider().TryGetResource("Common.Menu.Message.ConfirmacaoExclusaoFavoritoTodasEmpresas"), SinacorMessageBoxButton.YesNo, SinacorMessageBoxImage.Question) == SinacorMessageBoxResult.Yes)
            {
                if (_favoritesManager.RemoveFavorite(cls.ParentMenu.Assembly, cls.ParentMenu.ClassName))
                {
                    RootMenuItem rootMenuItem = ((RootMenuItem)this._menu.Items[2]);

                    foreach (FavoriteMenuItem menu in rootMenuItem.Items)
                    {
                        for (int i = menu.Items.Count - 1; i >= 0; i--)
                        {
                            if (menu.Items[i] is FavoriteSubMenuItem &&
                                ((FavoriteSubMenuItem)menu.Items[i]).Assembly == cls.ParentMenu.Assembly &&
                                ((FavoriteSubMenuItem)menu.Items[i]).ClassName == cls.ParentMenu.ClassName &&
                                !((FavoriteSubMenuItem)menu.Items[i]).CompanyId.HasValue)
                            {
                                menu.Items.RemoveAt(i);

                                ShowFavoritesIcons(new Favorite() { Assembly = cls.ParentMenu.Assembly, ClassName = cls.ParentMenu.ClassName });
                            }
                        }

                        if (menu.Items.Count > 0 && menu.Items[0] is Separator)
                            menu.Items.RemoveAt(0);
                    }
                }
            }
        }

        /// <summary>
        /// Evento que trata a exclusão de um favorito para a empresa selecionada no root-menu de favoritos
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        void ContextMenuPrivateFavorite_Click(object sender, RoutedEventArgs e)
        {
            ContextMenuItemFavorite cls = (ContextMenuItemFavorite)e.OriginalSource;

            string message = (string)ResourceProviderManager.GetResourceProvider().TryGetResource("Common.Menu.Message.ConfirmacaoExclusaoFavoritoSomenteEmpresa", cls.ParentMenu.ParentMenu.CompanyName);

            if (SinacorMessageBox.Show(message, SinacorMessageBoxButton.YesNo, SinacorMessageBoxImage.Question) == SinacorMessageBoxResult.Yes)
            {
                if (_favoritesManager.RemoveFavorite(cls.ParentMenu.ParentMenu.CompanyID, cls.ParentMenu.Assembly, cls.ParentMenu.ClassName))
                {
                    RootMenuItem rootMenuItem = ((RootMenuItem)this._menu.Items[2]);

                    foreach (FavoriteMenuItem menu in rootMenuItem.Items)
                    {
                        if (menu.CompanyID == cls.ParentMenu.ParentMenu.CompanyID)
                        {
                            for (int i = menu.Items.Count - 1; i >= 0; i--)
                            {
                                if (menu.Items[i] is FavoriteSubMenuItem &&
                                    ((FavoriteSubMenuItem)menu.Items[i]).Assembly == cls.ParentMenu.Assembly &&
                                    ((FavoriteSubMenuItem)menu.Items[i]).ClassName == cls.ParentMenu.ClassName &&
                                    ((FavoriteSubMenuItem)menu.Items[i]).CompanyId.Value == cls.ParentMenu.ParentMenu.CompanyID)
                                {
                                    menu.Items.RemoveAt(i);

                                    ShowFavoritesIcons(new Favorite() { Assembly = cls.ParentMenu.Assembly, ClassName = cls.ParentMenu.ClassName });
                                }
                            }
                        }
                    }
                }
            }
        }

        /// <summary>
        /// Evento que trata a abertura do contexmenu do root-menu de módulos
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        void ContextMenuModule_Opened(object sender, RoutedEventArgs e)
        {
            ContextMenuItemModule itemAllCompany = (ContextMenuItemModule)_contextMenuModule.Items[0];
            ContextMenuItemModule itemCompany = (ContextMenuItemModule)_contextMenuModule.Items[1];
            ContextMenuItemModule itemExcludeAllCompany = (ContextMenuItemModule)_contextMenuModule.Items[2];
            ContextMenuItemModule itemExcludeCompany = (ContextMenuItemModule)_contextMenuModule.Items[3];
            SubMenuItem subMenuItem = (SubMenuItem)_contextMenuModule.PlacementTarget;

            itemExcludeCompany.ParentMenu = itemExcludeAllCompany.ParentMenu = itemAllCompany.ParentMenu = itemCompany.ParentMenu = subMenuItem;
            itemCompany.Header = string.Format(FindResource("Common.Menu.Message.AdicionarFavoritoSomenteEmpresa").ToString(), this._menu.SelectedCompany);
            itemExcludeCompany.Header = string.Format(FindResource("Common.Menu.Message.ExcluirFavoritoEmpresaSomenteEmpresa").ToString(), this._menu.SelectedCompany);

            List<Favorite> favorites = _favoritesManager.GetAllCompaniesFavorites();
            List<CompanyFavorite> companyFavorites = _favoritesManager.GetCompanyFavorites(this._menu.SelectedCompanyId);

            Favorite favorite = favorites.Find(f => f.Assembly == subMenuItem.SubItemAssembly && f.ClassName == subMenuItem.SubItemClass);
            CompanyFavorite companyFavorite = companyFavorites.Find(f => f.Assembly == subMenuItem.SubItemAssembly && f.ClassName == subMenuItem.SubItemClass);

            itemAllCompany.Visibility = (favorite != null || companyFavorite != null) ? Visibility.Collapsed : Visibility.Visible;
            itemCompany.Visibility = (favorite != null || companyFavorite != null) ? Visibility.Collapsed : Visibility.Visible;
            itemExcludeAllCompany.Visibility = (favorite != null && companyFavorite == null) ? Visibility.Visible : Visibility.Collapsed;
            itemExcludeCompany.Visibility = (favorite == null && companyFavorite != null) ? Visibility.Visible : Visibility.Collapsed;
        }

        /// <summary>
        /// Evento que trata a abertura do contexmenu dos favoritos publicos
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        void ContextMenuPublicFavorite_Opened(object sender, RoutedEventArgs e)
        {
            ContextMenuItemFavorite item = (ContextMenuItemFavorite)_contextMenuPublicFavorite.Items[0];

            item.ParentMenu = (FavoriteSubMenuItem)_contextMenuPublicFavorite.PlacementTarget;
        }

        /// <summary>
        /// Evento que trata a abertura do contexmenu dos favoritos privados
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        void ContextMenuPrivateFavorite_Opened(object sender, RoutedEventArgs e)
        {
            ContextMenuItemFavorite item = (ContextMenuItemFavorite)_contextMenuPrivateFavorite.Items[0];

            item.ParentMenu = (FavoriteSubMenuItem)_contextMenuPrivateFavorite.PlacementTarget;
            item.Header = string.Format(item.Header.ToString(), ((FavoriteSubMenuItem)_contextMenuPrivateFavorite.PlacementTarget).ParentMenu.CompanyName);
        }

        #endregion

        #region Favorites

        /// <summary>
        /// Carrega os favoritos a partir das configurações do usuário ao carregar o menu
        /// </summary>
        /// <param name="companies"></param>
        void LoadFavorites()
        {
            RootMenuItem rootMenuItem = ((RootMenuItem)this._menu.Items[2]);
            rootMenuItem.Items.Clear();

            rootMenuItem.IsEnabled = true;

            foreach (Company company in _companies)
            {
                FavoriteMenuItem favoriteMenuItem = new FavoriteMenuItem(company.Id, company.Name, company.CGC, company.Name);

                List<Favorite> favorites = _favoritesManager.GetAllCompaniesFavorites();
                List<CompanyFavorite> companyFavorites = _favoritesManager.GetCompanyFavorites(company.Id);

                foreach (Favorite favorite in favorites)
                {
                    if (_presenter.CheckRolePermission(favorite.Role, favorite.ModuleId, company.Id))
                    {
                        FavoriteSubMenuItem favoriteSubMenuItem = new FavoriteSubMenuItem(favorite.Assembly, favorite.ClassName, favorite.ModuleName, favorite.ItemName, favoriteMenuItem, "IconMenuFavorite", favorite.Role);
                        favoriteSubMenuItem.ContextMenu = _contextMenuPublicFavorite;
                        favoriteMenuItem.Items.Add(favoriteSubMenuItem);
                    }
                }

                if (favoriteMenuItem.Items.Count > 0)
                    favoriteMenuItem.Items.Add(new Separator());

                foreach (CompanyFavorite companyFavorite in companyFavorites)
                {
                    if (_presenter.CheckRolePermission(companyFavorite.Role, companyFavorite.ModuleId, company.Id))
                    {
                        FavoriteSubMenuItem favoriteSubMenuItem = new FavoriteSubMenuItem(companyFavorite.Assembly, companyFavorite.ClassName, companyFavorite.ModuleName, companyFavorite.ItemName, favoriteMenuItem, "IconMenuFavoriteBorder", companyFavorite.Role);
                        favoriteSubMenuItem.CompanyId = companyFavorite.CompanyId;
                        favoriteSubMenuItem.ContextMenu = _contextMenuPrivateFavorite;
                        favoriteMenuItem.Items.Add(favoriteSubMenuItem);
                    }
                }

                rootMenuItem.Items.Add(favoriteMenuItem);
            }
        }

        /// <summary>
        /// Método que inclui um item no menu favoritos para todas as empresas
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        void AddMenuItemFavoriteAllCompany(Favorite favorite)
        {
            RootMenuItem rootMenuItem = ((RootMenuItem)this._menu.Items[2]);

            foreach (FavoriteMenuItem menu in rootMenuItem.Items)
            {
                Company foundCompany = _companies.Find(c => c.Id == menu.CompanyID);

                if (foundCompany != null && _presenter.CheckRolePermission(favorite.Role, favorite.ModuleId, foundCompany.Id))
                {
                    FavoriteSubMenuItem favoriteSubMenuItem = new FavoriteSubMenuItem(favorite.Assembly, favorite.ClassName, favorite.ModuleName, favorite.ItemName, menu, "IconMenuFavorite", favorite.Role);
                    favoriteSubMenuItem.ContextMenu = _contextMenuPublicFavorite;
                    menu.Items.Insert(0, favoriteSubMenuItem);

                    if (menu.Items.OfType<Separator>().Count() == 0)
                        menu.Items.Insert(1, new Separator());
                }
            }
        }

        /// <summary>
        /// Método que inclui um item no menu favoritos para empresa selecionada
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        void AddMenuItemFavoriteCompany(CompanyFavorite companyFavorite)
        {
            RootMenuItem rootMenuItem = ((RootMenuItem)this._menu.Items[2]);

            foreach (FavoriteMenuItem menu in rootMenuItem.Items)
            {
                if (menu.CompanyID == _menu.SelectedCompanyId)
                {
                    FavoriteSubMenuItem favoriteSubMenuItem = new FavoriteSubMenuItem(companyFavorite.Assembly, companyFavorite.ClassName, companyFavorite.ModuleName, companyFavorite.ItemName, menu, "IconMenuFavoriteBorder", companyFavorite.Role);
                    favoriteSubMenuItem.CompanyId = _menu.SelectedCompanyId;
                    favoriteSubMenuItem.ContextMenu = _contextMenuPrivateFavorite;
                    menu.Items.Add(favoriteSubMenuItem);
                }
            }
        }

        /// <summary>
        /// Método que exclui um item no menu favoritos para todas as empresas
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        void RemoveMenuItemFavoriteAllCompany(Favorite favorite)
        {
            RootMenuItem rootMenuItem = ((RootMenuItem)this._menu.Items[2]);

            foreach (FavoriteMenuItem menu in rootMenuItem.Items)
            {
                for (int i = menu.Items.Count - 1; i >= 0; i--)
                {
                    if (menu.Items[i] is FavoriteSubMenuItem &&
                        ((FavoriteSubMenuItem)menu.Items[i]).Assembly == favorite.Assembly &&
                        ((FavoriteSubMenuItem)menu.Items[i]).ClassName == favorite.ClassName &&
                        !((FavoriteSubMenuItem)menu.Items[i]).CompanyId.HasValue)
                        menu.Items.RemoveAt(i);
                }

                if (menu.Items.Count > 0 && menu.Items[0] is Separator)
                    menu.Items.RemoveAt(0);
            }
        }

        /// <summary>
        /// Método que exclui um item no menu favoritos para empresa selecionada
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        void RemoveMenuItemFavoriteCompany(CompanyFavorite companyFavorite)
        {
            RootMenuItem rootMenuItem = ((RootMenuItem)this._menu.Items[2]);

            foreach (FavoriteMenuItem menu in rootMenuItem.Items)
            {
                if (menu.CompanyID == _menu.SelectedCompanyId)
                {
                    for (int i = menu.Items.Count - 1; i >= 0; i--)
                    {
                        if (menu.Items[i] is FavoriteSubMenuItem &&
                            ((FavoriteSubMenuItem)menu.Items[i]).Assembly == companyFavorite.Assembly &&
                            ((FavoriteSubMenuItem)menu.Items[i]).ClassName == companyFavorite.ClassName &&
                            ((FavoriteSubMenuItem)menu.Items[i]).CompanyId.Value == _menu.SelectedCompanyId)
                            menu.Items.RemoveAt(i);
                    }
                }
            }
        }

        /// <summary>
        /// Atualiza os icones de favoritos da SinacorWindow
        /// </summary>
        /// <param name="favorite"></param>
        void ShowFavoritesIcons(Favorite favorite)
        {
            foreach (KeyValuePair<string, List<SinacorWindow>> desktop in _virtualDesktop.GetDesktopVirtual())
            {
                foreach (SinacorWindow w in desktop.Value)
                {
                    InternalMessage message = new InternalMessage();
                    message.MessageId = MessageIds.WindowManager.SNC_WINDOW_CHECK_VISIBILITY_FAVORITES_ICONS;
                    message.Message = favorite;
                    _messageManager.SendMessage(message);
                }
            }
        }

        #endregion

        #region Support Methods
        /// <summary>
        /// Posiciona o menu de acordo com o estado atual após uma ação
        /// </summary>
        /// <param name="state">Estado atual do menu</param>
        void SetMenuPositionAfterAction(SinacorMenuState state)
        {
            this._menu.State = state;
        }

        /// <summary>
        /// Retira os itens de modulos para apresentar em seu lugar as telas de um modulo previamente selecionado
        /// </summary>
        void OverwriteModuleItems(string subItemModuleID)
        {
            int moduleIndex = 0;
            ItemCollection modules = ((RootMenuItem)_menu.Items[1]).Items;

            if (modules.Count > 0)
            {
                if (modules[0] is ModuleMenuItem)
                {
                    for (int i = 0; i < modules.Count; i++)
                    {
                        if (((ModuleMenuItem)modules[i]).ModuleID == subItemModuleID)
                        {
                            moduleIndex = i;
                            break;
                        }
                    }

                    ItemCollection moduleItems = ((ModuleMenuItem)((RootMenuItem)_menu.Items[1]).Items[moduleIndex]).Items;
                    ((RootMenuItem)_menu.Items[1]).Items.Clear();
                    ((RootMenuItem)_menu.Items[1]).SubMenuContainerType = RootMenuContentType.ModuleSubMenu;
                    ((RootMenuItem)_menu.Items[1]).CommandBindings.Add(new CommandBinding(SinacorMenuCommands.RollbackModules, RollbackModules_Click));

                    while (moduleItems.Count > 0)
                    {
                        SinacorMenuItem subItem = (SinacorMenuItem)moduleItems[0];
                        moduleItems.Remove(subItem);
                        ((RootMenuItem)_menu.Items[1]).Items.Add(subItem);
                    }
                }
            }
        }

        /// <summary>
        /// Altera a posição de "dockagem" do menu no controle
        /// </summary>
        /// <param name="state">Estado do menu ao dockar</param>
        void ChangeDockedMenuPosition(SinacorMenuState state)
        {
            this._dockPosition = state;
        }

        /// <summary>
        /// Habilita o item do menu "Modulos"
        /// </summary>
        public void EnableModuleMenuItem()
        {
            RootMenuItem moduleMenuItem = ((RootMenuItem)this._menu.Items[1]);
            moduleMenuItem.IsEnabled = true;
        }

        /// <summary>
        /// Limpa o item do menu "Modulos"
        /// </summary>
        public void ClearModuleMenuItem()
        {
            RootMenuItem modulosMenu = ((RootMenuItem)this._menu.Items[1]);
            modulosMenu.Items.Clear();
            modulosMenu.IsEnabled = false;
            _menu.SelectedCompany = string.Empty;
            _menu.SelectedCompanyId = 0;
        }

        /// <summary>
        /// Verifica se existe alguma tela modal ou algum message box aberto antes de troca o desktop virtual
        /// </summary>
        /// <returns></returns>
        bool CheckWindowHasPendingActions()
        {
            bool foundPendingCheckBox = false;

            foreach (SinacorWindow w in _virtualDesktop.GetDesktopVirtual(_sessionaManager.GetCurrentSession().TokenID))
            {
                if (w.HasPendingMessageBox || w.IsModalWindow)
                {
                    foundPendingCheckBox = true;
                    break;
                }
            }

            return foundPendingCheckBox;
        }

        /// <summary>
        /// Atualiza a lista de janelas abertas
        /// </summary>
        void RefreshOpenedWindowsList()
        {
            SinacorMenuItem openedWindows = ((SinacorMenuItem)this._menu.Items[6]);

            openedWindows.Items.Clear();

            Session session = _sessionaManager.GetCurrentSession();

            if (session != null)
            {
                foreach (SinacorWindow w in _virtualDesktop.GetDesktopVirtual(session.TokenID))
                {
                    string menuPath = "";
                    foreach (string path in w.MenuHeader)
                        menuPath += path + " > ";
                    openedWindows.Items.Add(new WindowMenuItem(w.GetHashCode(), menuPath.Substring(0, menuPath.Length - 3)));
                }
            }

            openedWindows.IsEnabled = openedWindows.Items.Count > 0 ? true : false;
        }
        #endregion
    }

    public class SinacorMenuItemConverter : IMultiValueConverter
    {
        public object Convert(object[] values, Type targetType, object parameter, System.Globalization.CultureInfo culture)
        {
            foreach (bool val in values)
            {
                if (!val)
                    return false;
            }
            return true;
        }

        public object[] ConvertBack(object value, Type[] targetTypes, object parameter, System.Globalization.CultureInfo culture)
        {
            return new object[] { System.Convert.ToBoolean(value), System.Convert.ToBoolean(value) };
        }
    }
}
